use super::simd_advanced::{MacdResult, BollingerResult, MacdParams, BollingerParams, SimdResult, SimdError};

/// CPU特性检测结果
#[derive(Debug, Clone, Copy)]
pub struct CpuFeatures {
    pub has_avx: bool,
    pub has_avx2: bool,
    pub has_avx512f: bool,
    pub has_fma: bool,
    pub has_sse4_1: bool,
    pub has_sse4_2: bool,
}

impl CpuFeatures {
    /// 检测当前CPU支持的特性
    pub fn detect() -> Self {
        #[cfg(target_arch = "x86_64")]
        {
            use std::arch::x86_64::*;
            
            let mut has_avx = false;
            let mut has_avx2 = false;
            let mut has_avx512f = false;
            let mut has_fma = false;
            let mut has_sse4_1 = false;
            let mut has_sse4_2 = false;
            
            unsafe {
                let cpuid = __cpuid(1);
                has_sse4_1 = (cpuid.ecx & (1 << 19)) != 0;
                has_sse4_2 = (cpuid.ecx & (1 << 20)) != 0;
                has_avx = (cpuid.ecx & (1 << 28)) != 0;
                has_fma = (cpuid.ecx & (1 << 12)) != 0;
                
                if __get_cpuid_max(0).0 >= 7 {
                    let cpuid = __cpuid_count(7, 0);
                    has_avx2 = (cpuid.ebx & (1 << 5)) != 0;
                    has_avx512f = (cpuid.ebx & (1 << 16)) != 0;
                }
            }
            
            Self {
                has_avx,
                has_avx2,
                has_avx512f,
                has_fma,
                has_sse4_1,
                has_sse4_2,
            }
        }
        
        #[cfg(not(target_arch = "x86_64"))]
        {
            Self {
                has_avx: false,
                has_avx2: false,
                has_avx512f: false,
                has_fma: false,
                has_sse4_1: false,
                has_sse4_2: false,
            }
        }
    }
}

/// 定义计算MACD和Bollinger Bands的主函数
pub fn compute_macd(
    prices: &[f64],
    params: &MacdParams,
    chunk_size: Option<usize>,
) -> SimdResult<MacdResult> {
    // 根据CPU特性选择最优实现
    let features = CpuFeatures::detect();
    
    if features.has_avx512f && features.has_fma {
        unsafe { compute_macd_avx512(prices, params, chunk_size) }
    } else {
        compute_macd_fallback(prices, params)
    }
}

pub fn compute_bollinger(
    prices: &[f64],
    params: &BollingerParams,
    chunk_size: Option<usize>,
) -> SimdResult<BollingerResult> {
    // 根据CPU特性选择最优实现
    let features = CpuFeatures::detect();
    
    if features.has_avx512f && features.has_fma {
        unsafe { compute_bollinger_avx512(prices, params, chunk_size) }
    } else {
        compute_bollinger_fallback(prices, params)
    }
}

/// AVX-512版本的MACD计算
pub unsafe fn compute_macd_avx512(
    prices: &[f64],
    params: &MacdParams,
    chunk_size: Option<usize>,
) -> SimdResult<MacdResult> {
    // 这里应该是AVX-512实现，目前使用fallback
    compute_macd_fallback(prices, params)
}

/// AVX-512版本的布林带计算
pub unsafe fn compute_bollinger_avx512(
    prices: &[f64],
    params: &BollingerParams,
    chunk_size: Option<usize>,
) -> SimdResult<BollingerResult> {
    // 这里应该是AVX-512实现，目前使用fallback
    compute_bollinger_fallback(prices, params)
}

/// 标量版本的MACD计算（后备实现）
pub fn compute_macd_fallback(
    prices: &[f64],
    params: &MacdParams,
) -> SimdResult<MacdResult> {
    let len = prices.len();
    let mut result = MacdResult::with_capacity(len);

    // 计算快速EMA
    let mut fast_ema = vec![prices[0]];
    let fast_alpha = 2.0 / (params.fast_period as f64 + 1.0);
    let mut prev_fast = prices[0];

    for i in 1..len {
        prev_fast = fast_alpha * prices[i] + (1.0 - fast_alpha) * prev_fast;
        fast_ema.push(prev_fast);
    }
    result.fast_ema = fast_ema;

    // 计算慢速EMA
    let mut slow_ema = vec![prices[0]];
    let slow_alpha = 2.0 / (params.slow_period as f64 + 1.0);
    let mut prev_slow = prices[0];

    for i in 1..len {
        prev_slow = slow_alpha * prices[i] + (1.0 - slow_alpha) * prev_slow;
        slow_ema.push(prev_slow);
    }
    result.slow_ema = slow_ema;

    // 计算MACD线
    let mut macd = Vec::with_capacity(len);
    for i in 0..len {
        macd.push(result.fast_ema[i] - result.slow_ema[i]);
    }
    result.macd = macd;

    // 计算信号线
    let mut signal = vec![result.macd[0]];
    let signal_alpha = 2.0 / (params.signal_period as f64 + 1.0);
    let mut prev_signal = result.macd[0];

    for i in 1..len {
        prev_signal = signal_alpha * result.macd[i] + (1.0 - signal_alpha) * prev_signal;
        signal.push(prev_signal);
    }
    result.signal = signal;

    // 计算MACD柱状图
    let mut histogram = Vec::with_capacity(len);
    for i in 0..len {
        histogram.push(result.macd[i] - result.signal[i]);
    }
    result.histogram = histogram;

    // 验证结果
    result.validate()?;

    Ok(result)
}

/// 标量版本的布林带计算（后备实现）
pub fn compute_bollinger_fallback(
    prices: &[f64],
    params: &BollingerParams,
) -> SimdResult<BollingerResult> {
    let len = prices.len();
    let mut result = BollingerResult::with_capacity(len);

    // 填充前period-1个位置为NaN
    for _ in 0..params.period-1 {
        result.middle.push(f64::NAN);
        result.upper.push(f64::NAN);
        result.lower.push(f64::NAN);
        result.bandwidth.push(f64::NAN);
        result.std_dev.push(f64::NAN);
    }

    // 计算移动平均和标准差
    for i in params.period-1..len {
        let window = &prices[i - params.period + 1..=i];
        let sma = window.iter().sum::<f64>() / params.period as f64;
        
        let variance = window.iter()
            .map(|&price| {
                let diff = price - sma;
                diff * diff
            })
            .sum::<f64>() / params.period as f64;
        
        let std_dev = variance.sqrt();
        let std_mult = std_dev * params.num_std;

        result.middle.push(sma);
        result.std_dev.push(std_dev);
        result.upper.push(sma + std_mult);
        result.lower.push(sma - std_mult);
        result.bandwidth.push(2.0 * std_mult / sma);
    }

    // 验证结果
    result.validate()?;

    Ok(result)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::Instant;

    fn generate_test_prices(len: usize) -> Vec<f64> {
        let mut prices = Vec::with_capacity(len);
        for i in 0..len {
            prices.push(100.0 + (i as f64).sin() * 10.0);
        }
        prices
    }

    #[test]
    fn test_macd_calculation() {
        let prices = generate_test_prices(1000);
        let params = MacdParams::default();
        
        // 测试自动选择实现
        let result = compute_macd(&prices, &params, None);
        assert!(result.is_ok());
        let macd = result.unwrap();

        // 验证结果长度
        assert_eq!(macd.macd.len(), prices.len());
        assert_eq!(macd.signal.len(), prices.len());
        assert_eq!(macd.histogram.len(), prices.len());

        // 验证MACD计算逻辑
        for i in params.slow_period..prices.len() {
            assert_eq!(
                macd.macd[i],
                macd.fast_ema[i] - macd.slow_ema[i]
            );
            assert_eq!(
                macd.histogram[i],
                macd.macd[i] - macd.signal[i]
            );
        }
    }

    #[test]
    fn test_bollinger_calculation() {
        let prices = generate_test_prices(1000);
        let params = BollingerParams::default();
        
        // 测试自动选择实现
        let result = compute_bollinger(&prices, &params, None);
        assert!(result.is_ok());
        let bb = result.unwrap();

        // 验证结果长度
        assert_eq!(bb.middle.len(), prices.len());
        assert_eq!(bb.upper.len(), prices.len());
        assert_eq!(bb.lower.len(), prices.len());

        // 验证布林带计算逻辑
        for i in params.period..prices.len() {
            assert!(bb.upper[i] > bb.middle[i]);
            assert!(bb.lower[i] < bb.middle[i]);
            assert!((bb.upper[i] - bb.middle[i]).abs() - (bb.middle[i] - bb.lower[i]).abs() < 1e-10);
        }
    }

    #[test]
    fn test_implementations_comparison() {
        let prices = generate_test_prices(1000);
        
        // 测试MACD
        let macd_params = MacdParams::default();
        let macd_avx512 = unsafe { compute_macd_avx512(&prices, &macd_params, None).unwrap() };
        let macd_fallback = compute_macd_fallback(&prices, &macd_params).unwrap();

        for i in 0..prices.len() {
            assert!((macd_avx512.macd[i] - macd_fallback.macd[i]).abs() < 1e-10);
            assert!((macd_avx512.signal[i] - macd_fallback.signal[i]).abs() < 1e-10);
        }

        // 测试布林带
        let bb_params = BollingerParams::default();
        let bb_avx512 = unsafe { compute_bollinger_avx512(&prices, &bb_params, None).unwrap() };
        let bb_fallback = compute_bollinger_fallback(&prices, &bb_params).unwrap();

        for i in bb_params.period..prices.len() {
            assert!((bb_avx512.middle[i] - bb_fallback.middle[i]).abs() < 1e-10);
            assert!((bb_avx512.upper[i] - bb_fallback.upper[i]).abs() < 1e-10);
            assert!((bb_avx512.lower[i] - bb_fallback.lower[i]).abs() < 1e-10);
        }
    }

    #[test]
    fn test_performance() {
        let sizes = [1000, 10000, 100000, 1000000];
        
        println!("\nMACD Performance Tests:");
        let macd_params = MacdParams::default();
        for &size in &sizes {
            let prices = generate_test_prices(size);
            
            let start = Instant::now();
            let _ = unsafe { compute_macd_avx512(&prices, &macd_params, None).unwrap() };
            let avx512_time = start.elapsed();

            let start = Instant::now();
            let _ = compute_macd_fallback(&prices, &macd_params).unwrap();
            let scalar_time = start.elapsed();

            println!("Size: {}, AVX-512: {:?}, Scalar: {:?}, Speedup: {:.2}x",
                size, avx512_time, scalar_time, 
                scalar_time.as_secs_f64() / avx512_time.as_secs_f64());
        }

        println!("\nBollinger Bands Performance Tests:");
        let bb_params = BollingerParams::default();
        for &size in &sizes {
            let prices = generate_test_prices(size);
            
            let start = Instant::now();
            let _ = unsafe { compute_bollinger_avx512(&prices, &bb_params, None).unwrap() };
            let avx512_time = start.elapsed();

            let start = Instant::now();
            let _ = compute_bollinger_fallback(&prices, &bb_params).unwrap();
            let scalar_time = start.elapsed();

            println!("Size: {}, AVX-512: {:?}, Scalar: {:?}, Speedup: {:.2}x",
                size, avx512_time, scalar_time, 
                scalar_time.as_secs_f64() / avx512_time.as_secs_f64());
        }
    }

    #[test]
    fn test_cpu_features() {
        let features = CpuFeatures::detect();
        println!("CPU Features: {:?}", features);
        
        // 测试特性检测的一致性
        let features2 = CpuFeatures::detect();
        assert_eq!(features.has_avx2, features2.has_avx2);
        assert_eq!(features.has_avx512f, features2.has_avx512f);
        assert_eq!(features.has_fma, features2.has_fma);
    }

    #[test]
    fn test_chunk_sizes() {
        let prices = generate_test_prices(100000);
        let chunk_sizes = [256, 512, 1024, 2048, 4096];
        
        println!("\nMACD Chunk Size Tests:");
        let macd_params = MacdParams::default();
        for &chunk_size in &chunk_sizes {
            let start = Instant::now();
            let _ = compute_macd(&prices, &macd_params, Some(chunk_size)).unwrap();
            let time = start.elapsed();
            println!("Chunk size: {}, Time: {:?}", chunk_size, time);
        }

        println!("\nBollinger Bands Chunk Size Tests:");
        let bb_params = BollingerParams::default();
        for &chunk_size in &chunk_sizes {
            let start = Instant::now();
            let _ = compute_bollinger(&prices, &bb_params, Some(chunk_size)).unwrap();
            let time = start.elapsed();
            println!("Chunk size: {}, Time: {:?}", chunk_size, time);
        }
    }
}